package com.alvis.media.utility;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.ExecutionException;

/**
 * Python调用工具类
 * 用于在Java中执行Python脚本或命令
 * @author
 */
public class PythonUtil {

    private static final Logger logger = LoggerFactory.getLogger(PythonUtil.class);
    
    /**
     * 执行Python脚本
     * @param pythonPath Python解释器路径
     * @param scriptPath 脚本文件路径
     * @return 执行结果
     * @throws IOException IO异常
     * @throws InterruptedException 中断异常
     */
    public static String executeScript(String pythonPath, String scriptPath) throws IOException, InterruptedException {
        return executeScript(pythonPath, scriptPath, null);
    }
    
    /**
     * 执行Python脚本并传递参数
     * @param pythonPath Python解释器路径
     * @param scriptPath 脚本文件路径
     * @param args 命令行参数列表
     * @return 执行结果
     * @throws IOException IO异常
     * @throws InterruptedException 中断异常
     */
    public static String executeScript(String pythonPath, String scriptPath, List<String> args) throws IOException, InterruptedException {
        List<String> command = new ArrayList<>();
        command.add(pythonPath);
        command.add(scriptPath);
        
        if (args != null && !args.isEmpty()) {
            command.addAll(args);
        }
        
        return executeCommand(command);
    }
    
    /**
     * 执行Python代码字符串
     * @param pythonPath Python解释器路径
     * @param code Python代码字符串
     * @return 执行结果
     * @throws IOException IO异常
     * @throws InterruptedException 中断异常
     */
    public static String executeCode(String pythonPath, String code) throws IOException, InterruptedException {
        List<String> command = new ArrayList<>();
        command.add(pythonPath);
        command.add("-c");
        command.add(code);
        
        return executeCommand(command);
    }
    
    /**
     * 执行Python脚本并设置超时时间
     * @param pythonPath Python解释器路径
     * @param scriptPath 脚本文件路径
     * @param args 命令行参数列表
     * @param timeoutSeconds 超时时间（秒）
     * @return 执行结果
     * @throws IOException IO异常
     * @throws InterruptedException 中断异常
     * @throws TimeoutException 超时异常
     */
    public static String executeScriptWithTimeout(String pythonPath, String scriptPath, List<String> args, long timeoutSeconds) 
            throws IOException, InterruptedException, TimeoutException {
        List<String> command = new ArrayList<>();
        command.add(pythonPath);
        command.add(scriptPath);
        
        if (args != null && !args.isEmpty()) {
            command.addAll(args);
        }
        
        return executeCommandWithTimeout(command, timeoutSeconds);
    }
    
    /**
     * 执行命令列表
     * @param command 命令列表
     * @return 执行结果
     * @throws IOException IO异常
     * @throws InterruptedException 中断异常
     */
    private static String executeCommand(List<String> command) throws IOException, InterruptedException {
        ProcessBuilder pb = new ProcessBuilder(command);
        pb.redirectErrorStream(true); // 将错误输出合并到标准输出
        
        // 设置环境变量确保UTF-8编码
        Map<String, String> env = pb.environment();
        env.put("PYTHONIOENCODING", "UTF-8");
        env.put("PYTHONUTF8", "1");
        
        Process process = pb.start();
        StringBuilder output = new StringBuilder();
        
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
            }
        }
        
        int exitCode = process.waitFor();
        logger.info("Python command executed with exit code: {}", exitCode);
        
        if (exitCode != 0) {
            logger.error("Python command failed with exit code: {}, output: {}", exitCode, output.toString());
            throw new IOException("Python command failed with exit code: " + exitCode + ", output: " + output.toString());
        }
        
        return output.toString();
    }
    
    /**
     * 执行命令列表并设置超时时间
     * @param command 命令列表
     * @param timeoutSeconds 超时时间（秒）
     * @return 执行结果
     * @throws IOException IO异常
     * @throws InterruptedException 中断异常
     * @throws TimeoutException 超时异常
     */
    private static String executeCommandWithTimeout(List<String> command, long timeoutSeconds) 
            throws IOException, InterruptedException, TimeoutException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Callable<String> task = () -> executeCommand(command);
        Future<String> future = executor.submit(task);
        
        try {
            return future.get(timeoutSeconds, TimeUnit.SECONDS);
        } catch (TimeoutException e) {
            future.cancel(true);
            logger.error("Python command execution timed out after {} seconds", timeoutSeconds);
            throw e;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.error("Python command execution was interrupted", e);
            throw new RuntimeException("Python command execution was interrupted", e);
        } catch (ExecutionException e) {
            logger.error("Error executing Python command", e);
            throw new RuntimeException("Error executing Python command: " + e.getCause().getMessage(), e.getCause());
        } finally {
            executor.shutdownNow();
        }
    }
    
    /**
     * 检查Python环境是否可用
     * @param pythonPath Python解释器路径
     * @return 是否可用
     */
    public static boolean checkPythonEnvironment(String pythonPath) {
        try {
            List<String> command = new ArrayList<>();
            command.add(pythonPath);
            command.add("--version");
            
            ProcessBuilder pb = new ProcessBuilder(command);
            Process process = pb.start();
            int exitCode = process.waitFor();
            return exitCode == 0;
        } catch (Exception e) {
            logger.error("Failed to check Python environment: {}", e.getMessage());
            return false;
        }
    }
    
    /**
     * 获取Python版本
     * @param pythonPath Python解释器路径
     * @return Python版本信息
     */
    public static String getPythonVersion(String pythonPath) {
        try {
            List<String> command = new ArrayList<>();
            command.add(pythonPath);
            command.add("--version");
            
            ProcessBuilder pb = new ProcessBuilder(command);
            pb.redirectErrorStream(true);
            Process process = pb.start();
            
            StringBuilder output = new StringBuilder();
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    output.append(line).append("\n");
                }
            }
            
            process.waitFor();
            return output.toString().trim();
        } catch (Exception e) {
            logger.error("Failed to get Python version: {}", e.getMessage());
            return null;
        }
    }
}